(function ($) {
    "use strict";
    $.fn.popup = function (opts) {
        return new Popup(this[0], opts);
    };

    var queue = [];
    var Popup = function (containerEl, opts) {

        if (typeof containerEl === "string" || containerEl instanceof String) {
            this.container = document.getElementById(containerEl);
        } else {
            this.container = containerEl;
        }
        if (!this.container) {
            return;
        }

		if (typeof (opts) === "string" || typeof (opts) === "number")
			opts = {
				message: opts,
				cancelOnly: "true",
				cancelText: "OK"
			};
		this.id = opts.id = opts.id || this.uuid(); //opts is passed by reference
		this.addCssClass = opts.addCssClass ? opts.addCssClass : "";
		this.suppressTitle = opts.suppressTitle || this.suppressTitle;
		this.title = opts.suppressTitle ? "" : (opts.title || "Alert");
		this.message = opts.message || "";
		this.cancelText = opts.cancelText || "Cancel";
		this.cancelCallback = opts.cancelCallback || function () {};
		this.cancelClass = opts.cancelClass || "button";
		this.doneText = opts.doneText || "Done";
		this.doneCallback = opts.doneCallback || function () {
			// no action by default
		};
		this.doneClass = opts.doneClass || "button";
		this.cancelOnly = opts.cancelOnly || false;
		this.onShow = opts.onShow || function () {};
		this.autoCloseDone = opts.autoCloseDone !== undefined ? opts.autoCloseDone : true;

		queue.push(this);
		if (queue.length === 1)
			this.show();

    };

    Popup.prototype = {
        id: null,
        addCssClass: null,
        title: null,
        message: null,
        cancelText: null,
        cancelCallback: null,
        cancelClass: null,
        doneText: null,
        doneCallback: null,
        doneClass: null,
        cancelOnly: false,
        onShow: null,
        autoCloseDone: true,
        suppressTitle: false,
        show: function () {
            var self = this;
            var markup = "<div id='" + this.id + "' class='afPopup hidden "+ this.addCssClass + "'>"+
                        "<header>" + this.title + "</header>"+
                        "<div>" + this.message + "</div>"+
                        "<footer>"+
                             "<a href='javascript:;' class='" + this.cancelClass + "' id='cancel'>" + this.cancelText + "</a>"+
                             "<a href='javascript:;' class='" + this.doneClass + "' id='action'>" + this.doneText + "</a>"+
                             "<div style='clear:both'></div>"+
                        "</footer>"+
                        "</div>";

            var $el=$(markup);
            $(this.container).append($el);
            $el.bind("close", function () {
                self.hide();
            });

            if (this.cancelOnly) {
                $el.find("A#action").hide();
                $el.find("A#cancel").addClass("center");
            }
            $el.find("A").each(function () {
                var button = $(this);
                button.bind("click", function (e) {
                    if (button.attr("id") === "cancel") {
                        self.cancelCallback.call(self.cancelCallback, self);
                        self.hide();
                    } else {
                        self.doneCallback.call(self.doneCallback, self);
                        if (self.autoCloseDone)
                            self.hide();
                    }
                    e.preventDefault();
                });
            });
            self.positionPopup();
            $.blockUI(0.5);

            $el.bind("orientationchange", function () {
                self.positionPopup();
            });

            //force header/footer showing to fix CSS style bugs			
            $el.find("header").show();
            $el.find("footer").show();
			
            setTimeout(function(){
                $el.removeClass("hidden").addClass("show");
                self.onShow(self);
            },50);
			
        },

        hide: function () {
            var self = this;
            $("#" + self.id).addClass("hidden");
            $.unblockUI();
            self.remove();
        },

        remove: function () {
            var self = this;
            var $el = $("#" + self.id);
            $el.unbind("close");
            $el.find("BUTTON#action").unbind("click");
            $el.find("BUTTON#cancel").unbind("click");
            $el.unbind("orientationchange").remove();
            queue.splice(0, 1);
            if (queue.length > 0)
                queue[0].show();
        },

        positionPopup: function () {
            var popup = $("#" + this.id);

            popup.css("top", ((window.innerHeight / 2.5) + window.pageYOffset) - (popup[0].clientHeight / 2) + "px");
            popup.css("left", (window.innerWidth / 2) - (popup[0].clientWidth / 2) + "px");
        },

		uuid: function () {
			var S4 = function () {
				return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
			};
			return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
		}
    };
    var uiBlocked = false;
    $.blockUI = function (opacity) {
        if (uiBlocked)
            return;
        opacity = opacity ? " style='opacity:" + opacity + ";'" : "";
        $("BODY").prepend($("<div id='mask'" + opacity + "></div>"));
        $("BODY DIV#mask").bind("touchstart", function (e) {
            e.preventDefault();
        });
        $("BODY DIV#mask").bind("touchmove", function (e) {
            e.preventDefault();
        });
        uiBlocked = true;
    };

    $.unblockUI = function () {
        uiBlocked = false;
        $("BODY DIV#mask").unbind("touchstart");
        $("BODY DIV#mask").unbind("touchmove");
        $("BODY DIV#mask").remove();
    };

    $.popup=function(opts){
        return $(document.body).popup(opts);
    };
})($);
